/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
 * Author: Huawei OS Kernel Lab
 * Create: Thu Aug 15 16:14:23 2023
 * liblinux Vendor Hooks
 */

#if !defined(_TRACE_HOOK_LIBLINUX_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_HOOK_LIBLINUX_H

#undef TRACE_SYSTEM
#define TRACE_SYSTEM liblinux
#define TRACE_INCLUDE_PATH trace/hooks

#include <trace/hooks/vendor_hooks.h>
#include <asm-generic/module.h>
#include <linux/elf.h>

#ifndef TRACE_HEADER_MULTI_READ
/* mem stat dfx api */
enum liblinux_dfx_mem_event {
	LIBLINUX_DFX_MEM_MIN,
	LIBLINUX_DFX_SLAB_ALLOC,
	LIBLINUX_DFX_SLAB_FREE,
	LIBLINUX_DFX_PAGE_ALLOC,
	LIBLINUX_DFX_PAGE_FREE,
	LIBLINUX_DFX_VMALLOC_ALLOC,
	LIBLINUX_DFX_VMALLOC_FREE,
	LIBLINUX_DFX_MEM_MAX,
};
#endif

#ifndef CONFIG_LIBLINUX
#define DECLARE_LDK_HOOK(name, proto, args) \
	static inline void trace_##name(proto) {} \
	static inline bool trace_##name##_enabled(void) { return false; }

#define DECLARE_LDK_RESTRICTED_HOOK(name, proto, arg, cond) \
	DECLARE_LDK_HOOK(name, PARAMS(proto), PARAMS(args))
#else
#define DECLARE_LDK_HOOK DECLARE_HOOK
#define DECLARE_LDK_RESTRICTED_HOOK DECLARE_RESTRICTED_HOOK
#endif

#define HOOK_ALWAYS_ON 1
#define HOOK_ALWAYS_OFF 0

/* drivers/base/power/wakeup.c */
typedef void (*split_counters_t)(unsigned int *cnt, unsigned int *inpr);
DECLARE_LDK_RESTRICTED_HOOK(ldk_rvh_wakeup_source_activate,
	     TP_PROTO(bool is_activate, split_counters_t split_counters_f),
	     TP_ARGS(is_activate, split_counters_f),
	     TP_CONDITION(HOOK_ALWAYS_ON)
);

/*
 * ldk_vh_dfx_call_mem used in:
 * mm/{slab.h, slub.c, slab_common.c}
 * mm/pal/page_alloc.c
 */
DECLARE_LDK_RESTRICTED_HOOK(ldk_rvh_dfx_call_mem,
	     TP_PROTO(enum liblinux_dfx_mem_event ev_enum, void *addr,
		      unsigned long size, const char *slab_cache_name),
	     TP_ARGS(ev_enum, addr, size, slab_cache_name),
	     TP_CONDITION(HOOK_ALWAYS_ON)
);

/* fs/char_dev.c */
#define VH_REG_REGION 0
#define VH_UNREG_REGION 1
DECLARE_LDK_RESTRICTED_HOOK(ldk_rvh_chrdev_region,
	     TP_PROTO(int action, unsigned int *major, unsigned int baseminor,
		      int minorct, const char *name, int *ret),
	     TP_ARGS(action, major, baseminor, minorct, name, ret),
	     TP_CONDITION(HOOK_ALWAYS_ON)
);
DECLARE_LDK_RESTRICTED_HOOK(ldk_rvh_blkdev_region,
	     TP_PROTO(int action, unsigned int *major,
		      const char *name, int *ret),
	     TP_ARGS(action, major, name, ret),
	     TP_CONDITION(HOOK_ALWAYS_ON)
);

/* kernel/module.c */
struct module;
DECLARE_LDK_RESTRICTED_HOOK(ldk_rvh_module_frob_sections,
	     TP_PROTO(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
		      char *secstrings, struct module *mod),
	     TP_ARGS(ehdr, sechdrs, secstrings, mod),
	     TP_CONDITION(HOOK_ALWAYS_ON)
);
DECLARE_LDK_RESTRICTED_HOOK(ldk_rvh_apply_relocations,
	     TP_PROTO(Elf_Shdr *sechdrs, unsigned int symindex,
		      unsigned int relsec, struct module *me, int *ret),
	     TP_ARGS(sechdrs, symindex, relsec, me, ret),
	     TP_CONDITION(HOOK_ALWAYS_ON)
);

/* fs/kernfs/file.c */
DECLARE_LDK_RESTRICTED_HOOK(ldk_rvh_find_file_in_blacklist,
	     TP_PROTO(struct kernfs_node *parent, const char *name, bool *hit),
	     TP_ARGS(parent, name, hit),
	     TP_CONDITION(HOOK_ALWAYS_ON)
);

/* fs/kernfs */
struct kernfs_node;
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_kernfs_add_one,
			TP_PROTO(struct kernfs_node *kn, void (*remove)(struct kernfs_node *), int *ret),
			TP_ARGS(kn, remove, ret), HOOK_ALWAYS_ON);
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_kernfs_put,
			TP_PROTO(struct kernfs_node *kn, int *ret),
			TP_ARGS(kn, ret), HOOK_ALWAYS_ON);

DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_kernfs_notify,
			TP_PROTO(struct kernfs_node *kn),
			TP_ARGS(kn), HOOK_ALWAYS_ON);

/* fs/procfs/generic.c */
#define VH_REG_PROCFS_PREPARE 0
#define VH_REG_PROCFS 1
struct proc_dir_entry;
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_proc_register,
	     TP_PROTO(int action, struct proc_dir_entry *dp),
	     TP_ARGS(action, dp), HOOK_ALWAYS_ON);
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_remove_proc_entry,
	     TP_PROTO(struct proc_dir_entry *de),
	     TP_ARGS(de), HOOK_ALWAYS_ON);
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_remove_proc_subtree,
	     TP_PROTO(struct proc_dir_entry *de),
	     TP_ARGS(de), HOOK_ALWAYS_ON);

/* fs/proc/proc_sysctl.c */
struct ctl_table;
struct ctl_table_header;
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_register_sysctl_table,
			TP_PROTO(const char *dir, struct ctl_table_header *head, struct ctl_table *table),
			TP_ARGS(dir, head, table), HOOK_ALWAYS_ON);

/* fs/sysfs */
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_sysfs_init,
			TP_PROTO(struct kernfs_root **root, struct file_system_type *sys_fs, int *ret),
			TP_ARGS(root, sys_fs, ret), HOOK_ALWAYS_ON);

/* drivers/base/firmware_loader/main.c */
struct device;
struct fw_priv;
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_fw_get_filesystem_firmware,
			TP_PROTO(struct device *device, struct fw_priv *fw_priv,
			const char *suffix,
			int (*decompress)(struct device *dev,
					  struct fw_priv *fw_priv,
					  size_t in_size,
					  const void *in_buffer),
			const char * const *fw_path,
			size_t fw_path_size, int *ret),
			TP_ARGS(device, fw_priv, suffix, decompress, fw_path, fw_path_size, ret),
			HOOK_ALWAYS_ON);

/* drivers/base/firmware_loader/main.c */
struct file_operations;
DECLARE_LDK_RESTRICTED_HOOK(ldk_vh_kmemleak_create_file,
			TP_PROTO(const struct file_operations *fops),
			TP_ARGS(fops),
			HOOK_ALWAYS_ON);

/* drivers/tty/tty_io.c */
struct tty_struct;
struct winsize;
DECLARE_LDK_RESTRICTED_HOOK(ldk_rvh_tty_process_signal,
	     TP_PROTO(struct tty_struct *tty, struct winsize *ws, bool *ret),
	     TP_ARGS(tty, ws, ret),
	     TP_CONDITION(HOOK_ALWAYS_ON)
);

#endif /* !defined(_TRACE_HOOK_LIBLINUX_H) || defined(TRACE_HEADER_MULTI_READ) */
/* This part must be outside protection */
#include <trace/define_trace.h>
